home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung 2 / Power-Programmierung CD 2 (Tewi)(1994).iso / gnu / gnulib / dkbtrace / pbmplus / source / ppm / ppmtoicr.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-06  |  7.2 KB  |  322 lines

  1. /* ppmtoicr.c - convert a portable pixmap to NCSA ICR protocol
  2. **
  3. ** Copyright (C) 1990 by Kanthan Pillay (svpillay@Princeton.EDU)
  4. **
  5. ** Permission to use, copy, modify, and distribute this software and its
  6. ** documentation for any purpose and without fee is hereby granted, provided
  7. ** that the above copyright notice appear in all copies and that both that
  8. ** copyright notice and this permission notice appear in supporting
  9. ** documentation.  This software is provided "as is" without express or
  10. ** implied warranty.
  11. */
  12.  
  13. #include "ppm.h"
  14. #include "ppmcmap.h"
  15.  
  16. #define MAXCOLORS 256
  17. #define CLUTCOLORS 768
  18.  
  19. static int colorstobpp ARGS(( int colors ));
  20. static int GetPixel ARGS(( int x, int y ));
  21. static int rleit ARGS(( char* buf, char* bufto, int len ));
  22.  
  23. static pixel** pixels;
  24. static colorhash_table cht;
  25. static char* testimage;
  26.  
  27. void
  28. main(argc, argv)
  29. int argc;
  30. char* argv[];
  31. {
  32.     FILE* ifp;
  33.     int argn, rows, cols, colors, i, j, BitsPerPixel, newxsize;
  34.     pixval maxval;
  35.     colorhist_vector chv;
  36.     char rgb[CLUTCOLORS];
  37.     char* windowname;
  38.     char* thischar;
  39.     char* thisline;
  40.     char* space;
  41.     register unsigned char c;
  42.     register char* p;
  43.     int display, expand;
  44.     int rleflag, winflag;
  45.     char* usage = "[-windowname windowname] [-expand expand] [-display display] [-rle] [ppmfile]";
  46.  
  47.     ppm_init( &argc, argv );
  48.  
  49.     argn = 1;
  50.     windowname = "untitled";
  51.     winflag = 0;
  52.     expand = 1;
  53.     display = 0;
  54.     rleflag = 0;
  55.  
  56.     while ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' )
  57.         {
  58.         if ( pm_keymatch(argv[argn],"-windowname",2) && argn + 1 < argc )
  59.         {
  60.         ++argn;
  61.         windowname = argv[argn];
  62.         winflag = 1;
  63.         }
  64.         else if ( pm_keymatch(argv[argn],"-expand",2) && argn + 1 < argc )
  65.         {
  66.         ++argn;
  67.         if ( sscanf( argv[argn], "%d",&expand ) != 1 )
  68.             pm_usage( usage );
  69.         }
  70.         else if ( pm_keymatch(argv[argn],"-display",2) && argn + 1 < argc )
  71.         {
  72.         ++argn;
  73.         if ( sscanf( argv[argn], "%d",&display ) != 1 )
  74.             pm_usage( usage );
  75.         }
  76.         else if ( pm_keymatch(argv[argn],"-rle",2) )
  77.         rleflag = 1;
  78.         else if ( pm_keymatch(argv[argn],"-norle",2) )
  79.         rleflag = 0;
  80.         else
  81.         pm_usage( usage );
  82.         }
  83.  
  84.     if ( argn < argc )
  85.         {
  86.         ifp = pm_openr( argv[argn] );
  87.         if ( ! winflag )
  88.         windowname = argv[argn];
  89.         ++argn;
  90.         }
  91.     else
  92.         ifp = stdin;
  93.  
  94.     if ( argn != argc )
  95.         pm_usage( usage );
  96.  
  97.     pixels = ppm_readppm( ifp, &cols, &rows, &maxval );
  98.  
  99.     pm_close( ifp );
  100.  
  101.     for (i = 0; i < CLUTCOLORS; i++)
  102.         rgb[i] = 0;
  103.  
  104.     /* Figure out the colormap. */
  105.     pm_message("computing colormap..." );
  106.     chv = ppm_computecolorhist(pixels, cols, rows, MAXCOLORS, &colors);
  107.     if (chv == (colorhist_vector) 0)
  108.     pm_error( "too many colors - try doing a 'ppmquant %d'", MAXCOLORS );
  109.     pm_message("%d colors found", colors );
  110.  
  111.     /* Turn the ppm colormap into an ICR colormap. */
  112.     if (maxval > 255)
  113.     pm_message(
  114.         "maxval is not 255 - automatically rescaling colors" );
  115.     for (i = 0; i < colors; i++)
  116.     {
  117.     j = (3 * i);
  118.     if (maxval == 255)
  119.         {
  120.         rgb[j] = PPM_GETR(chv[i].color) ;
  121.         j++;
  122.         rgb[j] = PPM_GETG(chv[i].color) ;
  123.         j++;
  124.         rgb[j] = PPM_GETB(chv[i].color) ;
  125.         }
  126.     else
  127.         {
  128.         rgb[j] = (int) PPM_GETR(chv[i].color) * 255 / maxval;
  129.         j++;
  130.         rgb[j] = (int) PPM_GETG(chv[i].color) * 255 / maxval;
  131.         j++;
  132.         rgb[j] = (int) PPM_GETB(chv[i].color) * 255 / maxval;
  133.         }
  134.     }
  135.     BitsPerPixel = colorstobpp(colors);
  136.  
  137.     /* And make a hash table for fast lookup. */
  138.     cht = ppm_colorhisttocolorhash(chv, colors);
  139.     ppm_freecolorhist(chv);
  140.  
  141.  
  142.     /************** Create a new window using ICR protocol *********/
  143.     /* Format is "ESC^W;left;top;width;height;display;windowname"  */
  144.  
  145.     pm_message("creating window %s ...", windowname );
  146.     (void)fprintf (stdout, "\033^W;%d;%d;%d;%d;%d;%s^",0,0,cols*expand,rows*expand,display,windowname);
  147.     fflush(stdout);
  148.  
  149.  
  150.     /****************** Download the colormap.  ********************/
  151.     pm_message("downloading colormap for %s ...", windowname );
  152.  
  153.     (void)fprintf (stdout, "\033^M;%d;%d;%d;%s^",0,MAXCOLORS,CLUTCOLORS,windowname);
  154.     thischar = rgb;
  155.     for (j=0; j<CLUTCOLORS; j++) {
  156.     c = *thischar++;
  157.         if (c > 31 && c < 123 ) {     /* printable ASCII */
  158.         putchar(c);
  159.         }
  160.         else {
  161.         putchar((c>>6)+123);     /* non-printable, so encode it */
  162.         putchar((c & 0x3f) + 32);
  163.         }
  164.     }
  165.     fflush(stdout);
  166.  
  167.     /**************** send out picture *************************/
  168.     /* Protocol's RLE scheme is quicker but buggy              */
  169.  
  170.     if (rleflag) {    
  171.         pm_message("sending run-length encoded picture data ..." );
  172.         testimage = (char*) malloc(rows*cols);
  173.         p = testimage;
  174.         for (i=0; i<rows; i++)
  175.             for (j=0; j<cols; j++) 
  176.             *p++ = GetPixel(j,i);
  177.         space = (char*) malloc(rows*3);
  178.         thisline = testimage;
  179.         for (i = 0; i < rows; i++) {
  180.             newxsize = rleit(thisline,space,cols);
  181.             thisline += cols;    /* increment to next line */
  182.         (void)fprintf (stdout, "\033^R;%d;%d;%d;%d;%s^",0,i*expand,expand,newxsize,windowname);
  183.         thischar = space;
  184.         for (j=0; j< newxsize; j++) {
  185.             c= *thischar++;  /*get byte to send */
  186.             if (c>31 && c <123) {
  187.                 putchar(c);
  188.                 }
  189.             else {
  190.                 putchar((c>>6) + 123);
  191.                 putchar((c & 0x3f) + 32);
  192.                 }
  193.             }
  194.             fflush(stdout);
  195.         }
  196.         free(space);
  197.         pm_close (stdout);
  198.         exit(0);
  199.         }
  200.  
  201.     /* Otherwise, send out uncompressed pixel data via the slow method */
  202.  
  203.         else {
  204.         pm_message("sending picture data ..." );
  205.         for (i = 0; i < rows; i++) {
  206.             (void)fprintf (stdout, "\033^P;%d;%d;%d;%d;%s^",0,i*expand,expand,cols,windowname);
  207.             for (j = 0; j < cols; j++) {
  208.                 c  = GetPixel(j,i);
  209.                 if (c > 31 && c < 123) {
  210.                         putchar(c);
  211.                         }
  212.                 else        {
  213.                         putchar((c>>6)+123);
  214.                         putchar((c & 0x3f) + 32);
  215.                         }
  216.                 }
  217.             }
  218.         pm_close (stdout);
  219.         exit(0);
  220.         }
  221.     }
  222.  
  223. static int
  224. colorstobpp(colors)
  225. int colors;
  226.     {
  227.     int bpp;
  228.  
  229.     if (colors <= 2)
  230.     bpp = 1;
  231.     else if (colors <= 4)
  232.     bpp = 2;
  233.     else if (colors <= 8)
  234.     bpp = 3;
  235.     else if (colors <= 16)
  236.     bpp = 4;
  237.     else if (colors <= 32)
  238.     bpp = 5;
  239.     else if (colors <= 64)
  240.     bpp = 6;
  241.     else if (colors <= 128)
  242.     bpp = 7;
  243.     else if (colors <= 256)
  244.     bpp = 8;
  245.     else
  246.     pm_error("can't happen" );
  247.     return bpp;
  248.     }
  249.  
  250. static int
  251. GetPixel(x, y)
  252. int x, y;
  253.     {
  254.     int color;
  255.  
  256.     color = ppm_lookupcolor(cht, &pixels[y][x]);
  257.     return color;
  258.     }
  259.  
  260.  
  261. /* rleit   compress with run length encoding as per NCSA's documentation */
  262.  
  263. static int
  264. rleit(buf,bufto,len)
  265.     char* buf;
  266.     char* bufto;
  267.     int len;
  268.     {
  269.     register char* p;
  270.     register char* q;
  271.     register char* cfoll;
  272.     register char* clead;
  273.     char* begp;
  274.     int i;
  275.  
  276.     p = buf;
  277.     cfoll = bufto;
  278.     clead = cfoll + 1;
  279.  
  280.     begp = p;
  281.     while (len > 0 ) {        /* encode until gone */
  282.         
  283.         q = p + 1;
  284.         i = len-1;
  285.     while (*p == *q && i+120 > len && i) {
  286.         q++;
  287.         i--;
  288.     }
  289.  
  290.     if (q > p +2) {            /* three in a row */
  291.         if (p > begp) {
  292.             *cfoll = p - begp;
  293.             cfoll = clead;
  294.         }
  295.         *cfoll++ = 128 | (q-p);        /*len of seq*/
  296.         *cfoll++ = *p;            /* char of seq */
  297.         len -= q-p;        /* subtract len of seq */
  298.         p = q;
  299.         clead = cfoll+1;
  300.         begp = p;
  301.     }
  302.     else {
  303.         *clead++ = *p++;    /* copy one char */
  304.         len--;
  305.         if (p>begp + 120) {
  306.             *cfoll = p - begp;
  307.             cfoll = clead++;
  308.             begp = p;
  309.         }
  310.     }
  311.     }
  312.  
  313. /* fillin last bytecount */
  314.  
  315.     if (p>begp)
  316.         *cfoll = (p - begp);
  317.     else
  318.         clead--;
  319.  
  320.     return((int) (clead-bufto));    /*how many stored as encoded */
  321. }
  322.